﻿using MQTTnet;
using MQTTnet.Protocol;
using MQTTnet.Server;
using Newtonsoft.Json;
using System.Text;

namespace Micro.Mqtt
{
    public abstract partial class MqttHost
    {
        /// <summary>
        /// 服务端定时器
        /// </summary>
        public virtual Timer ServerTimer { get; set; }

        /// <summary>
        /// 默认端口
        /// </summary>
        private const string DefaultPort = "8015";

        /// <summary>
        /// 监听端口：（多个端口之间用逗号隔开）
        /// </summary>
        public abstract string Prots { get; set; }

        /// <summary>
        /// 默认发送消息的客户端ClientId
        /// </summary>
        public abstract string ServerClientId { get; set; }

        /// <summary>
        /// Mqtt服务
        /// </summary>
        public MqttServer ServerHost;

        /// <summary>
        /// 服务端发送消息
        /// </summary>
        /// <param name="path"></param>
        /// <param name="data"></param>
        public virtual async Task Publish(string path, dynamic data)
        {
            if (ServerHost is null || data is null || string.IsNullOrEmpty(path)) return;
            var sendStr = data.GetType() == typeof(string) ? data : JsonConvert.SerializeObject(data);
            var message = new MqttApplicationMessage
            {
                Topic = path,
                PayloadSegment = Encoding.Default.GetBytes(sendStr),
                QualityOfServiceLevel = MqttQualityOfServiceLevel.AtLeastOnce,
                Retain = false  // 服务端是否保留消息。true为保留，如果有新的订阅者连接，就会立马收到该消息。
            };

            await ServerHost.InjectApplicationMessage(new InjectedMqttApplicationMessage(message) { SenderClientId = ServerClientId });// 发送消息给有订阅 的客户端
            Console.WriteLine($"【{GetType().Name}】：服务端发送： 消息=【{sendStr}】");
        }

        #region Mqtt服务端

        /// <summary>
        /// 启动Mqtt服务
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task StartAsync(CancellationToken cancellationToken)
        {
            // 设置mqtt 服务端 、端口号、安全验证规则
            var optionsBuilder = new MqttServerOptionsBuilder();
            //使用默认端点
            optionsBuilder.WithDefaultEndpoint();
            optionsBuilder.WithDefaultEndpointPort(int.Parse(DefaultPort));

            if (string.IsNullOrEmpty(Prots)) Prots = DefaultPort;
            var prots = Prots.Split(',').Select(int.Parse);
            foreach (var item in prots) optionsBuilder.WithDefaultEndpointPort(item);

            // 持续会话
            optionsBuilder.WithPersistentSessions(true);
            //最大连接数
            optionsBuilder.WithConnectionBacklog(3000);

            var options = optionsBuilder.Build();
            options.KeepAliveOptions.MonitorInterval = TimeSpan.FromSeconds(30);
            ServerHost = new MqttFactory().CreateMqttServer(options);

            //事件集合
            //验证
            ServerHost.ValidatingConnectionAsync += _mqttServer_ValidatingConnectionAsync; // 用户名和密码验证有关

            //服务启动
            ServerHost.StartedAsync += _mqttServer_StartedAsync;//启动
            ServerHost.StoppedAsync += _mqttServer_StopedAsync;//停止

            //客户端连接
            ServerHost.ClientConnectedAsync += _mqttServer_ClienConnectedAsync;//连接成功
            ServerHost.ClientDisconnectedAsync += _mqttServer_ClienDisConnectedAsync;//断开连接

            //客户端订阅 取消
            ServerHost.ClientSubscribedTopicAsync += _mqttServer_ClientSubscribedTopicAsync; // 客户端订阅主题事件
            ServerHost.ClientUnsubscribedTopicAsync += _mqttServer_ClientUnsubscribedTopicAsync; // 客户端取消订阅事件

            //消息接收
            ServerHost.ApplicationMessageNotConsumedAsync += _mqttServer_ApplicationMessageNotConsumedAsync; // 消息未接收事件
            ServerHost.InterceptingPublishAsync += _mqttServer_InterceptingPublishAsync; // 消息事件

            ServerHost.StartAsync().GetAwaiter().GetResult();

            await Task.Run(() =>
            {
                // 创建并启动 Timer 实例，并设置定时器间隔为5分钟
                ServerTimer = new Timer(_ =>
                {
                    try
                    {
                        Console.WriteLine($"【{GetType().Name}】【{Prots}】：客户端数量：{ServerHost.GetClientsAsync().GetAwaiter().GetResult().Count}");
                    }
                    catch { }
                }, default, TimeSpan.FromSeconds(60), TimeSpan.FromSeconds(60 * 5));
            });
        }

        /// <summary>
        /// 客户端连接
        /// </summary>
        /// <param name="args"></param>
        /// <returns></returns>
        public virtual async Task _mqttServer_ClienConnectedAsync(ClientConnectedEventArgs args)
        {
            Console.WriteLine($"【{GetType().Name}】：客户端连接_mqttServer_ClienConnectedAsync：客户端ID: 【{args.ClientId}】连接成功！");
            await Task.CompletedTask;
        }

        /// <summary>
        /// 客户端断开连接
        /// </summary>
        /// <param name="args"></param>
        /// <returns></returns>
        public virtual async Task _mqttServer_ClienDisConnectedAsync(ClientDisconnectedEventArgs args)
        {
            Console.WriteLine($"【{GetType().Name}】：客户端断开连接_mqttServer_ClienDisConnectedAsync：客户端ID: 【{args.ClientId}】断开连接！");
            await Task.CompletedTask;
        }

        /// <summary>
        /// Mqtt服务启动事件
        /// </summary>
        /// <param name="args"></param>
        /// <returns></returns>
        public virtual async Task _mqttServer_StartedAsync(EventArgs args)
        {
            Console.WriteLine($"【Mqtt：{GetType().Name}】服务启动成功，端口【{Prots}】！");
            await Task.CompletedTask;
        }

        /// <summary>
        /// Mqtt服务停止事件
        /// </summary>
        /// <param name="args"></param>
        /// <returns></returns>
        public virtual async Task _mqttServer_StopedAsync(EventArgs args)
        {
            Console.WriteLine($"【{GetType().Name}】：Mqtt服务停止成功！");
            await Task.CompletedTask;
        }

        /// <summary>
        /// 客户端订阅
        /// </summary>
        /// <param name="arg"></param>
        /// <returns></returns>
        public virtual async Task _mqttServer_ClientSubscribedTopicAsync(ClientSubscribedTopicEventArgs arg)
        {
            Console.WriteLine($"【{GetType().Name}】：客户端订阅_mqttServer_ClientSubscribedTopicAsync：客户端ID=【{arg.ClientId}】订阅的主题=【{arg.TopicFilter}】！");
            await Task.CompletedTask;
        }

        /// <summary>
        /// 客户端取消订阅
        /// </summary>
        /// <param name="arg"></param>
        /// <returns></returns>
        public virtual async Task _mqttServer_ClientUnsubscribedTopicAsync(ClientUnsubscribedTopicEventArgs arg)
        {
            Console.WriteLine($"【{GetType().Name}】：客户端取消订阅_mqttServer_ClientUnsubscribedTopicAsync：客户端ID=【{arg.ClientId}】已取消订阅的主题=【{arg.TopicFilter}】！");
            await Task.CompletedTask;
        }

        /// <summary>
        /// 接收消息
        /// </summary>
        /// <param name="arg"></param>
        /// <returns></returns>
        public virtual async Task _mqttServer_InterceptingPublishAsync(InterceptingPublishEventArgs arg)
        {
            if (arg.ClientId == ServerClientId) return;
            Console.WriteLine($"【{GetType().Name}】：接收消息_mqttServer_InterceptingPublishAsync：客户端ID=【{arg.ClientId}】 Topic主题=【{arg.ApplicationMessage.Topic}】 消息=【{Encoding.UTF8.GetString(arg.ApplicationMessage.PayloadSegment)}】 qos等级=【{arg.ApplicationMessage.QualityOfServiceLevel}】！");
            await Publish($"{arg.ApplicationMessage.Topic}/Mqtt", Encoding.UTF8.GetString(arg.ApplicationMessage.PayloadSegment));
        }

        /// <summary>
        /// 未接收消息
        /// </summary>
        /// <param name="arg"></param>
        /// <returns></returns>
        public virtual async Task _mqttServer_ApplicationMessageNotConsumedAsync(ApplicationMessageNotConsumedEventArgs arg)
        {
            if (arg.SenderId == ServerClientId) return;
            Console.WriteLine($"【{GetType().Name}】：未接收消息_mqttServer_ApplicationMessageNotConsumedAsync：发送端ID=【{arg.SenderId}】 Topic主题=【{arg.ApplicationMessage.Topic}】 消息=【{Encoding.UTF8.GetString(arg.ApplicationMessage.PayloadSegment)}】 qos等级=【{arg.ApplicationMessage.QualityOfServiceLevel}】！");
            await Task.CompletedTask;
        }

        /// <summary>
        /// 用户、密码校验
        /// </summary>
        /// <param name="arg"></param>
        /// <returns></returns>
        public virtual async Task _mqttServer_ValidatingConnectionAsync(ValidatingConnectionEventArgs arg)
        {
            var userName = arg.UserName;
            var password = arg.Password;
            //arg.ReasonCode = MqttConnectReasonCode.Banned;
            arg.ReasonCode = MqttConnectReasonCode.Success;
            Console.WriteLine($"【{GetType().Name}】：密码较验成功【_mqttServer_ValidatingConnectionAsync】 ");
            await Task.CompletedTask;
        }

        /// <summary>
        /// 停止Mqtt服务端
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task StopAsync(CancellationToken cancellationToken)
        {
            await Task.Run(() =>
            {
                ServerHost = default;
                Console.WriteLine($"【{GetType().Name}】：Mqtt服务端结束成功【StopAsync】 ");
            });
        }

        #endregion Mqtt服务端
    }
}